package com.matthicks.macrobot;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import javax.imageio.ImageIO;

public class CommandListener extends Thread {
	private ServerSocket server;
	
	public CommandListener(String host, int port) throws IOException {
		if (host != null) {
			server = new ServerSocket();
			server.bind(new InetSocketAddress(host, port));
		} else {
			server = new ServerSocket(port);
		}
		System.out.println("Server bound to " + server.getInetAddress() + ":" + server.getLocalPort());
	}
	
	public void run() {
		System.out.println("CommandListener started. Waiting for connection...");
		while (true) {
			try {
				Socket socket = server.accept();
				if (socket != null) {
					System.out.println("Connection established: " + socket.getRemoteSocketAddress());
					try {
						InputStream input = socket.getInputStream();
						DataOutputStream output = new DataOutputStream(socket.getOutputStream());
						BufferedReader reader = new BufferedReader(new InputStreamReader(input));
						String line;
						while ((line = reader.readLine()) != null) {
							Command command = new Command(line);
							System.out.println("Received command: " + command);
							if (command.name.equals("disconnect")) {
								break;
							} else if (command.name.equals("shutdown")) {
								System.out.println("Shutting down by request.");
								System.exit(0);
							}
							CommandResponse response = Controller.get().processCommand(command);
							output.writeBoolean(response.successful);
							if (response.payload != null) {
								if (response.payload instanceof BufferedImage) {
									ByteArrayOutputStream baos = new ByteArrayOutputStream();
									ImageIO.write((BufferedImage)response.payload, "png", baos);
									ImageWrapper wrapper = new ImageWrapper();
									wrapper.data = baos.toByteArray();
									response.payload = wrapper;
								}
								
								ByteArrayOutputStream baos = new ByteArrayOutputStream();
								ObjectOutputStream oos = new ObjectOutputStream(baos);
								oos.writeObject(response.payload);
								byte[] buf = baos.toByteArray();
								output.writeInt(buf.length);
								output.write(buf);
							} else {
								output.writeInt(-1);
							}
							output.flush();
						}
					} finally {
						System.out.println("Closing connection.");
						socket.close();
					}
				}
			} catch(SocketException exc) {
				System.err.println("Socket connection lost.");
			} catch(Exception exc) {
				exc.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		CommandListener cl = new CommandListener(null, 2600);
		cl.start();
	}
}